package view.console;

import controller.Controller;
import filesystem.exceptions.InvalidModelItemException;
import model.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Iterator;

/**
 * Console view class
 */
public class ConsoleView {

    private ArtistView artistView = new ArtistView();
    private AlbumView albumView = new AlbumView();
    private GenreView genreView = new GenreView();
    private TrackView trackView = new TrackView();
    private Controller controller = new Controller();
    private String mainMenu = new String("1. Показать все треки\n2. Показать все жанры\n3. Показать всех артистов\n4. Показать все альбомы\n0. Выход\n");
    private String itemsMenu = new String("1. Добавить\n2. Удалить\n3. Редактировать\n4. Поиск\n0. Главное меню\n");

    public ConsoleView(Controller controller) {
        this.controller = controller;
    }

    /**
     * Start menu
     */
    public void startMenu() {
        BufferedReader commandReader = null;
        try {
            commandReader = new BufferedReader(new InputStreamReader(System.in, "Cp1251"));
        } catch (UnsupportedEncodingException e) {
            System.out.println("Невозможно инициализировать программу. Неподдерживаемая кодировка.");
            return;
        }
        int command = 0;
        do {
            System.out.println(mainMenu);
            System.out.print("Введите номер команды: ");
            try {
                command = Integer.valueOf(commandReader.readLine());
                if (command < 0 || command > 4) {
                    throw new IllegalArgumentException();
                }
            } catch (IOException ex) {
                System.out.println("Неверные данные");
                continue;
            } catch (IllegalArgumentException e) {
                System.out.print("Пожалуйста, введите корректную команду (для выхода введите 0). ");
                continue;
            }
            switch (command) {
                case 1:
                    try {
                        trackView.showItems(controller.selectItem(trackView.getModel(), "*"));
                        startItemsMenu(commandReader, command, trackView);
                    } catch (IOException e) {
                        System.out.println("Ошибка при работе с файловой системой");
                        continue;
                    }
                    break;
                case 2:
                    try {
                        genreView.showItems(controller.selectItem(genreView.getModel(), "*"));
                        startItemsMenu(commandReader, command, genreView);
                    } catch (IOException e) {
                        System.out.println("Ошибка при работе с файловой системой");
                        continue;
                    }
                    break;
                case 3:
                    try {
                        artistView.showItems(controller.selectItem(artistView.getModel(), "*"));
                        startItemsMenu(commandReader, command, artistView);
                    } catch (IOException e) {
                        System.out.println("Ошибка при работе с файловой системой");
                        continue;
                    }
                    break;
                case 4:
                    try {
                        albumView.showItems(controller.selectItem(albumView.getModel(), "*"));
                        startItemsMenu(commandReader, command, albumView);
                    } catch (IOException e) {
                        System.out.println("Ошибка при работе с файловой системой");
                        continue;
                    }
                    break;
            }
        } while (command != 0);
        return;
    }

    /**
     * Control menu of model for edit, add, remove and search
     *
     * @param commandReader - command for options
     * @param menuItem - command from startMenu
     * @param item - model
     */
    public void startItemsMenu(BufferedReader commandReader, int menuItem, ItemView item) {
        int command = 0;
        do {
            System.out.println(itemsMenu);
            System.out.print("Введите номер команды: ");
            try {
                command = Integer.valueOf(commandReader.readLine());
                if (command < 0 || command > 4) {
                    throw new IllegalArgumentException();
                }
            } catch (IOException e) {
                System.out.println("Произошла ошибка ввода/вывода");
                return;
            } catch (IllegalArgumentException e) {
                System.out.print("\nПожалуйста, введите корректную команду (для выхода в главное меню введите 0).\n\n");
                continue;
            }
            switch (command) {
                //добавить объект
                case 1:
                    addItemMenu(commandReader, menuItem);
                    return;
                //удалить объект
                case 2:
                    removeItemMenu(commandReader, menuItem, item);
                    return;
                //редактировать объект
                case 3:
                    editItemMenu(commandReader, menuItem, item);
                    return;
                //поиск
                case 4:
                    searchItemMenu(commandReader, menuItem, item);
                    return;
                case 0:
                    return;
                default:
                    System.out.println("\nНеверный номер команды\n\n");
                    break;
            }
        } while (command != 0);
    }

    public void editItemMenu(BufferedReader commandReader, int object, ItemView item) {
        int num = -1;
        System.out.print("Введите номер объекта: ");
        try {
            num = Integer.valueOf(commandReader.readLine());
        } catch (IOException ex) {
            System.out.println("\nОшибка ввода/вывода\n\n");
            return;
        } catch (NumberFormatException ex) {
            System.out.println("\nНомер объекта должен состоять из цифр!\n\n");
            return;
        }
        switch (object) {
            case 1:
                try {
                    //получаем нужный трек
                    ModelItem track = (Track) trackView.getModel().getItems().get(num - 1);
                    //редактируем
                    System.out.print("Введите название трека: ");
                    String name = commandReader.readLine();
                    System.out.print("Введите имя исполнителя: ");
                    Artist artist = new Artist(commandReader.readLine());
                    System.out.print("Введите название альбома: ");
                    Album album = new Album(commandReader.readLine());
                    System.out.print("Введите жанр трека: ");
                    Genre genre = new Genre(commandReader.readLine());
                    System.out.print("Введите продолжительность трека: ");
                    int len = Integer.valueOf(commandReader.readLine());
                    System.out.print("Введите размер трека: ");
                    int size = Integer.valueOf(commandReader.readLine());
                    if (len < 0 || size < 0) {
                        System.out.print("\nВведены некорректные данные. Операция не выполнена.\n\n");
                        return;
                    }
                    ((Track) track).setName(name);
                    ((Track) track).setArtist(artist);
                    ((Track) track).setAlbum(album);
                    ((Track) track).setGenre(genre);
                    ((Track) track).setLength(len);
                    ((Track) track).setSize(size);

                    if (track != null) {
                        controller.execute(Controller.operation.EDIT, trackView.getModel(), track);
                    }
                } catch (IllegalArgumentException e) {
                    System.out.print("\nВведены некорректные данные. Операция не выполнена.\n\n");
                    return;
                } catch (IndexOutOfBoundsException e) {
                    System.out.print("\nОбъект с данным номером не существует.\n\n");
                    return;
                } catch (IOException e) {
                    System.out.println("\nОшибка ввода/вывода\n\n");
                    return;
                } catch (InvalidModelItemException e) {
                    System.out.println("\nНесоответствие данных.\n\n");
                    return;
                }
                break;
            case 2:
                try {
                    //получаем нужный жанр
                    ModelItem genre = (Genre) genreView.getModel().getItems().get(num - 1);
                    //редактируем
                    System.out.print("Введите название жанра: ");
                    ((Genre) genre).setName(commandReader.readLine());
                    controller.execute(Controller.operation.EDIT, genreView.getModel(), genre);
                } catch (IllegalArgumentException e) {
                    System.out.print("\nОбъект с данным номером не существует.\n\n");
                    return;
                } catch (IndexOutOfBoundsException e) {
                    System.out.print("\nОбъект с данным номером не существует.\n\n");
                    return;
                } catch (IOException e) {
                    System.out.println("\nОшибка ввода/вывода\n\n");
                    return;
                } catch (InvalidModelItemException e) {
                    System.out.println("\nНесоответствие данных.\n\n");
                    return;
                }
                break;
            case 3:
                try {
                    //получаем нужного артиста
                    ModelItem artist = (Artist) artistView.getModel().getItems().get(num - 1);
                    //редактируем
                    System.out.print("Введите имя исполнителя: ");
                    ((Artist) artist).setName(commandReader.readLine());
                    controller.execute(Controller.operation.EDIT, artistView.getModel(), artist);
                } catch (IllegalArgumentException e) {
                    System.out.print("\nОбъект с данным номером не существует.\n\n");
                    return;
                } catch (IndexOutOfBoundsException e) {
                    System.out.print("\nОбъект с данным номером не существует.\n\n");
                    return;
                } catch (IOException e) {
                    System.out.println("\nОшибка ввода/вывода\n\n");
                    return;
                } catch (InvalidModelItemException e) {
                    System.out.println("\nНесоответствие данных.\n\n");
                    return;
                }
                break;
            case 4:
                try {
                    //получаем нужный альбом
                    ModelItem album = (Album) albumView.getModel().getItems().get(num - 1);
                    //редактируем
                    System.out.print("Введите название альбома: ");
                    ((Album) album).setName(commandReader.readLine());
                    controller.execute(Controller.operation.EDIT, albumView.getModel(), album);
                } catch (IllegalArgumentException e) {
                    System.out.print("\nОбъект с данным номером не существует.\n\n");
                    return;
                } catch (IndexOutOfBoundsException e) {
                    System.out.print("\nОбъект с данным номером не существует.\n\n");
                    return;
                } catch (IOException e) {
                    System.out.println("\nОшибка ввода/вывода\n\n");
                    return;
                } catch (InvalidModelItemException e) {
                    System.out.println("\nНесоответствие данных.\n\n");
                    return;
                }
                break;
        }
        System.out.print("\nОбъект успешно изменен\n\n");

    }

    public void addItemMenu(BufferedReader commandReader, int object) {
        ModelItem item = null;
        switch (object) {
            //если добавляем трек
            case 1:
                try {
                    System.out.print("Введите название трека: ");
                    String title = commandReader.readLine();
                    System.out.print("Введите имя исполнителя: ");
                    String artist = commandReader.readLine();
                    System.out.print("Введите название альбома: ");
                    String album = commandReader.readLine();
                    System.out.print("Введите жанр трека: ");
                    String genre = commandReader.readLine();
                    System.out.print("Введите продолжительность трека: ");
                    int length = Integer.valueOf(commandReader.readLine());
                    System.out.print("Введите размер трека: ");
                    int size = Integer.valueOf(commandReader.readLine());
                    if (length < 0 || size < 0) {
                        System.out.print("\nВведены некорректные данные. Операция не выполнена.\n\n");
                        return;
                    }
                    item = new Track(title, new Artist(artist), new Album(album),
                            new Genre(genre), length, size);
                    controller.execute(Controller.operation.ADD, trackView.getModel(), item);
                } catch (IllegalArgumentException e) {
                    System.out.print("\nПожалуйста, введите корректную команду (для выхода в главное меню введите 0).\n\n");
                    break;
                } catch (IOException e) {
                    System.out.println("\nОшибка ввода/вывода\n\n");
                    return;
                } catch (InvalidModelItemException e) {
                    System.out.println("\nНесоответствие данных.\n\n");
                    return;
                }
                break;
            //жанр
            case 2:
                try {
                    System.out.print("Введите название жанра: ");
                    String genre = commandReader.readLine();
                    item = new Genre(genre);
                    controller.execute(Controller.operation.ADD, genreView.getModel(), item);
                } catch (IllegalArgumentException e) {
                    System.out.print("\nПожалуйста, введите корректную команду (для выхода в главное меню введите 0).\n\n");
                    break;
                } catch (IOException e) {
                    System.out.println("\nОшибка ввода/вывода\n\n");
                    return;
                } catch (InvalidModelItemException e) {
                    System.out.println("\nНесоответствие данных.\n\n");
                    return;
                }
                break;
            //исполнитель
            case 3:
                try {
                    System.out.print("Введите имя исполнителя: ");
                    String artist = commandReader.readLine();
                    item = new Artist(artist);
                    controller.execute(Controller.operation.ADD, artistView.getModel(), item);
                } catch (IllegalArgumentException e) {
                    System.out.print("\nПожалуйста, введите корректную команду (для выхода в главное меню введите 0).\n\n");
                    break;
                } catch (IOException e) {
                    System.out.println("\nОшибка ввода/вывода\n\n");
                    return;
                } catch (InvalidModelItemException e) {
                    System.out.println("\nНесоответствие данных.\n\n");
                    return;
                }
                break;
            //альбом
            case 4:
                try {
                    System.out.print("Введите название альбома: ");
                    String album = commandReader.readLine();
                    item = new Album(album);
                    controller.execute(Controller.operation.ADD, albumView.getModel(), item);
                } catch (IllegalArgumentException e) {
                    System.out.print("\nПожалуйста, введите корректную команду (для выхода в главное меню введите 0).\n\n");
                    break;
                } catch (IOException e) {
                    System.out.println("\nОшибка ввода/вывода\n\n");
                    return;
                } catch (InvalidModelItemException e) {
                    System.out.println("\nНесоответствие данных.\n\n");
                    return;
                }
                break;
        }
        System.out.print("\nНовый объект добавлен\n\n");
    }

    public void removeItemMenu(BufferedReader commandReader, int object, ItemView item) {
        int num = -1;
        System.out.print("Введите номер объекта: ");
        try {
            num = Integer.valueOf(commandReader.readLine());
        } catch (IOException ex) {
            System.out.println("\nОшибка ввода/вывода\n\n");
            return;
        } catch (NumberFormatException ex) {
            System.out.println("\nНомер объекта должен состоять из цифр!\n\n");
            return;
        }
        switch (object) {
            //если удаляем трек
            case 1:
                try {
                    //получаем нужный трек
                    ModelItem deleting = (Track) trackView.getModel().getItems().get(num - 1);
                    if (deleting != null) {
                        controller.execute(Controller.operation.REMOVE, trackView.getModel(), deleting);
                    }
                } catch (IllegalArgumentException e) {
                    System.out.print("\nОбъект с данным номером не существует.\n\n");
                    return;
                } catch (IndexOutOfBoundsException e) {
                    System.out.print("\nОбъект с данным номером не существует.\n\n");
                    return;
                } catch (IOException e) {
                    System.out.println("\nОшибка ввода/вывода\n\n");
                    return;
                } catch (InvalidModelItemException e) {
                    System.out.println("\nНесоответствие данных.\n\n");
                    return;
                }
                break;
            //жанр
            case 2:
                try {
                    ModelItem deleting = (Genre) genreView.getModel().getItems().get(num - 1);
                    if (deleting != null) {
                        controller.execute(Controller.operation.REMOVE, genreView.getModel(), deleting);
                    }
                } catch (IllegalArgumentException e) {
                    System.out.print("\nОбъект с данным номером не существует.\n\n");
                    return;
                } catch (IndexOutOfBoundsException e) {
                    System.out.print("\nОбъект с данным номером не существует.\n\n");
                    return;
                } catch (IOException e) {
                    System.out.println("\nОшибка ввода/вывода\n\n");
                    return;
                } catch (InvalidModelItemException e) {
                    System.out.println("\nНесоответствие данных.\n\n");
                    return;
                }
                break;
            //исполнитель
            case 3:
                try {
                    ModelItem deleting = (Artist) artistView.getModel().getItems().get(num - 1);
                    if (deleting != null) {
                        controller.execute(Controller.operation.REMOVE, artistView.getModel(), deleting);
                    }
                } catch (IllegalArgumentException e) {
                    System.out.print("\nОбъект с данным номером не существует.\n\n");
                    return;
                } catch (IndexOutOfBoundsException e) {
                    System.out.print("\nОбъект с данным номером не существует.\n\n");
                    return;
                } catch (IOException e) {
                    System.out.println("\nОшибка ввода/вывода\n\n");
                    return;
                } catch (InvalidModelItemException e) {
                    System.out.println("\nНесоответствие данных.\n\n");
                    return;
                }
                break;
            //альбом
            case 4:
                try {
                    ModelItem deleting = (Album) albumView.getModel().getItems().get(num - 1);
                    //ModelItem deleting = (Album) ((BaseModel) albums).getItems().get(num - 1);
                    if (deleting != null) {
                        controller.execute(Controller.operation.REMOVE, albumView.getModel(), deleting);
                    }
                } catch (IllegalArgumentException e) {
                    System.out.print("\nОбъект с данным номером не существует.\n\n");
                    return;
                } catch (IndexOutOfBoundsException e) {
                    System.out.print("\nОбъект с данным номером не существует.\n\n");
                    return;
                } catch (IOException e) {
                    System.out.println("\nОшибка ввода/вывода\n\n");
                    return;
                } catch (InvalidModelItemException e) {
                    System.out.println("\nНесоответствие данных.\n\n");
                    return;
                }
                break;
        }
        System.out.println("\nОбъект удален\n\n");
    }

    public void searchItemMenu(BufferedReader commandReader, int object, ItemView item) {
        String name = "*";
        System.out.print("Введите название объекта: ");
        try {
            name = commandReader.readLine();
        } catch (IOException ex) {
            System.out.println("\nОшибка ввода/вывода\n\n");
            return;
        }
        switch (object) {
            case 1:
                TrackView trackSearch = (TrackView) item;
                try {
                    trackSearch.showItems(controller.selectItem(trackView.getModel(), name));
                    startItemsMenu(commandReader, object, trackSearch);
                } catch (IOException e) {
                    System.out.println("\nОшибка при работе с файловой системой\n\n");
                    return;
                }
                break;
            case 2:
                try {
                    GenreView genreSearch = (GenreView) item;
                    genreSearch.showItems(controller.selectItem(genreView.getModel(), name));
                    startItemsMenu(commandReader, object, genreSearch);
                } catch (IOException e) {
                    System.out.println("\nОшибка при работе с файловой системой\n\n");
                    return;
                }
                break;
            case 3:
                try {
                    ArtistView artistSearch = (ArtistView) item;
                    artistSearch.showItems(controller.selectItem(artistView.getModel(), name));
                    startItemsMenu(commandReader, object, artistSearch);
                } catch (IOException e) {
                    System.out.println("\nОшибка при работе с файловой системой\n\n");
                    return;
                }
                break;
            case 4:
                try {
                    AlbumView albumSearch = (AlbumView) item;
                    albumSearch.showItems(controller.selectItem(albumView.getModel(), name));
                    startItemsMenu(commandReader, object, albumSearch);
                } catch (IOException e) {
                    System.out.println("\nОшибка при работе с файловой системой\n\n");
                    return;
                }
                break;
        }
    }
}
